package com.example.snake;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class SnackFrame07 extends Frame {
    /*窗体宽高*/
    private static final int WINDOW_X = 600;
    private static final int WINDOW_Y = 500;
    /*上1 下3 左2 右0*/
    private static final int UP = 1;
    private static final int DOWN = 3;
    private static final int LEFT = 2;
    private static final int RIGHT = 0;

    /*速度*/
    private int refreshRate = 700;
    /*分数*/
    private int score = 0;
    /*控制程序是否继续*/
    private boolean isRunning = true;
    //上1 下3 右2 左0
    private int direction = 0;
    //食物
    private Node food = new Node(randomNum(0, WINDOW_X / 20 - 1) * 20, randomNum(2, WINDOW_Y / 20 - 1) * 20);
    //存储离屏图像
    private Image offScreenImage;

    /**
     * 蛇的主体部分
     */
    private Node[] body = {
            new Node(140, 100),
            new Node(120, 100),
            new Node(100, 100)
    };

    // 构造器中初始化窗体
    public SnackFrame07() {
        //设置距离显示器距离
        //this.setLocation(200,100);
        //获取屏幕尺寸
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        //计算窗口左上角x坐标
        int x = (screenSize.width - WINDOW_X) / 2;
        //计算窗口左上角y坐标
        int y = (screenSize.height - WINDOW_Y) / 2;
        //设置窗口位置
        this.setLocation(x, y);
        //设置窗口大小
        this.setSize(WINDOW_X, WINDOW_Y);
        //设置背景色
        this.setBackground(Color.magenta);
        this.setTitle("贪吃蛇V1.0");
        //禁止改变窗体大小
        this.setResizable(false);
        //添加窗口监听
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                //退出虚拟机
                System.exit(0);
            }
        });
        //监听键盘事件
        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                //上1 下3 右0 左2
                int dir = -1;
                switch (e.getKeyCode()) {
                    case KeyEvent.VK_UP://向上走
                        dir = 1;
                        break;
                    case KeyEvent.VK_DOWN://向下走
                        dir = 3;
                        break;
                    case KeyEvent.VK_LEFT://向左走
                        dir = 2;
                        break;
                    case KeyEvent.VK_RIGHT://向右走
                        dir = 0;
                        break;
                }
                //根据合法性来修改方向（不允许在同一条线上修改）
                if (direction % 2 != dir % 2) {
                    direction = dir;
                }
//                System.out.println("当前按键为:" + e.getKeyCode());
            }
        });

        //显示窗体
        this.setVisible(true);

        // 使用 Swing Timer 控制游戏的周期性更新
        new Timer(refreshRate, e -> gameUpdate()).start();
    }

    /**
     * 绘制窗体内容
     * 窗体显示 | 更新 自动调用
     *
     * @param g 画笔
     */
    @Override
    public void paint(Graphics g) {
        // 在这里绘制游戏界面
        // 清除上一次的绘制
        g.clearRect(0, 0, getWidth(), getHeight());

        // 设置蛇和食物的颜色和绘制
        g.setColor(Color.ORANGE);
        for (int i = 0; i < body.length; i++) {
            body[i].drawNode(g, i);
        }

        g.setColor(Color.BLUE);
        food.drawNode(g, -1);

        // 移动逻辑和食物检查已移至 gameUpdate 方法

        if (isRunning) {
            // 游戏正在运行，绘制蛇和食物
            g.setColor(Color.ORANGE);
            for (int i = 0; i < body.length; i++) {
                body[i].drawNode(g, i);
            }
            g.setColor(Color.BLUE);
            food.drawNode(g, -1);

            Font font1 = new Font("Arial", Font.BOLD, 15); // 设置字体、风格和大小
            g.setFont(font1);
            g.drawString("Score:" + score, 20, 50);
        } else {
            Font font = new Font("Arial", Font.BOLD, 30); // 设置字体、风格和大小
            g.setFont(font);
            // 游戏结束，显示结束信息
            g.setColor(Color.CYAN);
            g.drawString("Game Over!!!", WINDOW_X / 4, WINDOW_Y / 4);
            g.drawString("The space bar restarts", WINDOW_X / 4, WINDOW_Y / 4 + 50);
            g.drawString("score:" + score, WINDOW_X / 4, WINDOW_Y / 4 + 100);

            Font font1 = new Font("Arial", Font.BOLD, 15); // 设置字体、风格和大小
            g.setFont(font1);
            g.drawString("Score:" + score, 20, 50);
        }
    }

    @Override
    public void update(Graphics g) {
        if (offScreenImage == null) {
            offScreenImage = createImage(getWidth(), getHeight());
        }
        Graphics offG = offScreenImage.getGraphics();
        paint(offG);
        g.drawImage(offScreenImage, 0, 0, null);
    }

    /**
     * 增加吃到食物，增加蛇的身体，食物变为蛇的头部，食物重新生成
     */
    public void addBody() {
        Node[] temp = new Node[body.length + 1];
        temp[0] = food;
        System.arraycopy(body, 0, temp, 1, body.length);
        body = temp;
        food = null;
        productFood();//生成食物
        /*分数+1*/
        score++;
        /*显示*/
        setTitle("贪吃蛇V1.0 Score:" + score);
//                /*显示分数*/
//                new Graphics.drawString("分数:" + score, 0, 0);
    }

    /**
     * 是否吃到食物，下一步的头节点位置刚好和食物位置相等
     *
     * @return
     */
    public boolean isEat() {
        Node newHead = getNewHead();
        if (newHead.equals(food)) {
            return true;
        }
        return false;
    }

    /**
     * 随机产生食物
     */
    public void productFood() {
        food = new Node(randomNum(0, WINDOW_X / 20 - 1) * 20, randomNum(2, WINDOW_Y / 20 - 1) * 20);
    }

    /**
     * 重绘窗体
     */
    public void start() {
        // start 方法已被 Timer 替代
    }

    /**
     * 通过修改坐标达到移动效果
     */
    public void move() {
        /*向右移动*/
        /**
         *1. 每次给一个新的头节点，去掉尾节点
         * 2. 整体移动
         */
        Node[] temp = new Node[body.length];
        temp[0] = getNewHead();
        //拷贝数组 原数组，哪个地方开始拷贝，目标数组，目标数组的哪里，拷贝的长度
        System.arraycopy(body, 0, temp, 1, body.length - 1);
        this.body = temp;
    }

    /**
     * 根据方向确定新的头节点
     *
     * @return
     */
    public Node getNewHead() {
        Node newNode = body[0];
        //上1 下3 右0 左2
        switch (this.direction) {
            case RIGHT://向右走
                newNode = new Node(newNode.getX() + 20, newNode.getY());
                break;
            case LEFT://向左走
                newNode = new Node(newNode.getX() - 20, newNode.getY());
                break;
            case UP://向上走
                newNode = new Node(newNode.getX(), newNode.getY() - 20);
                break;
            case DOWN://向下走
                newNode = new Node(newNode.getX(), newNode.getY() + 20);
                break;
        }
        return newNode;
    }

    /**
     * 游戏逻辑更新
     */
    private void gameUpdate() {
//        System.out.println(isRunning);
//        System.out.println(body[0].getX());
//        System.out.println(body[0].getY());
        if (isRunning) {
            if (isEat()) {
                System.out.println("吃到食物了");
                addBody();
                // 在这里根据分数修改速度
                if (refreshRate > 100) {
                    if (score % 10 == 0) {
                        refreshRate -= 10;
                    }
                }
                new Timer(refreshRate, e -> gameUpdate()).start();// 更新计时器的速度
            } else {
                move();
            }
            isOver();
            repaint();
        } else {
//            g.drowString("Game Over!!!", WINDOW_X / 2, WINDOW_Y / 2);
//            System.out.println("Game Over!!!");
        }
    }

    /**
     * 根据min和max随机生成食物
     *
     * @param min
     * @param max
     * @return
     */
    public static int randomNum(int min, int max) {
        return (int) (Math.random() * (max - min + 1) + min); //随机数范围[min,max]
    }

    /**
     * @return true 游戏结束 false 游戏未结束
     */
    public void isOver() {
        Node head = body[0];
        //超出边界
        if (head.getX() <= 0 || head.getX() >= WINDOW_X - 20 || head.getY() <= 20 || head.getY() >= WINDOW_Y - 20) {
            isRunning = false;
        }
        //身体
        for (int i = 1; i < body.length; i++) {
            if (head.equals(body[i])) {
                isRunning = false;
            }
        }
    }

//    public static void main(String[] args) {
//        new SnackFrame07();
//    }
}
